from django.shortcuts import render
from rest_framework import status, viewsets
from rest_framework.response import Response
from rest_framework.views import APIView
from yaml import serializer
from apps.oaauth.models import OADepartment, OAUser, UserStatusChoices
from apps.oaauth.serializers import DepartmentSerializer, UserSerializer
from oaback.settings import DEFAULT_FROM_EMAIL
from .serializers import AddStaffSerializer, ActiveStaffSerializer, StaffUploadSerializer
from django.conf import settings
from utils import aeser
from django.urls import reverse
from oaback.celery import debug_task
from django.core.mail import send_mail
from .tasks import send_email_task
from rest_framework.decorators import action
from django.views import View
from django.http import JsonResponse
from urllib import parse
from rest_framework import exceptions
from datetime import datetime
import json
import pandas as pd
from django.http.response import HttpResponse
from django.db import transaction

aes = aeser.AESCipher(settings.SECRET_KEY)


# class DepartmentList(ListAPIView):
#     queryset = OADepartment.objects.all().order_by('id')
#     serializer_class = DepartmentSerializer

def send_active_email(request, email):
    # 使用AES算法对邮箱加密生成激活token
    token = aes.encrypt(email)
    active_path = reverse("staff:active_staff") + "?" + parse.urlencode({'token': token})
    active_url = request.build_absolute_uri(active_path)
    message = f"请点击以下链接激活账号:{active_url}"
    subject = 'OA系统账号激活'

    # 使用异步任务发送邮件，防止阻塞
    send_email_task.delay(email, subject, message)


class DepartmentList(viewsets.ModelViewSet):
    queryset = OADepartment.objects.all().order_by('id')
    serializer_class = DepartmentSerializer


# 新员工激活
class ActiveStaffView(View):
    def get(self, request):
        token = request.GET.get('token')
        response = render(request, 'active.html')
        response.set_cookie('token', token)
        return response

    def post(self, request):
        try:
            token = request.COOKIES.get('token')
            email = aes.decrypt(token)
            serializer = ActiveStaffSerializer(data=request.POST)
            if serializer.is_valid():
                form_email = serializer.validated_data.get('email')
                user = serializer.validated_data.get('user')
                if email != form_email:
                    return JsonResponse({"code": 400, "message": "邮箱错误"})
                user.status = UserStatusChoices.ACTIVED
                user.save()
                return JsonResponse({"code": 200, "message": "激活成功"})
            else:
                errors = serializer.errors
                non_field_errors = errors.get('non_field_errors', [])
                error_message = non_field_errors[0]
                # print(error_message)
                return JsonResponse({'code': 400, 'message': error_message})
        except Exception as e:
            return JsonResponse({'code': 400, 'message': "token错误"})


# 使用ModelViewSet构建StaffViewSet，包含基本的CRUD操作
class StaffViewSet(viewsets.ModelViewSet):
    queryset = OAUser.objects.all()  # 设置查询集
    serializer_class = AddStaffSerializer  # 设置序列化器

    def get_serializer_class(self):
        print(self.request.method)
        if self.request.method == 'POST':
            return AddStaffSerializer
        elif self.request.method == 'GET' or 'PUT':
            return UserSerializer


    def list(self, request, *args, **kwargs):

        # 获取前端传递的参数(条件搜索员工时使用)
        size = request.query_params.get('size')
        department_id = request.query_params.get('department_id')
        realname = request.query_params.get('realname')
        date_joined = request.query_params.getlist('date_joined[]')

        # 如果是董事会，返回所有员工；如果不是董事会，是部门leader，返回部门员工；普通员工抛出403
        # 返回员工列表时使用
        user = self.request.user
        department = user.department

        if user.department.name != '董事会':
            if user.uid != user.department.leader.uid:
                return JsonResponse({"detail": "没有权限查看"}, status=status.HTTP_403_FORBIDDEN)
            else:
                queryset = self.filter_queryset(self.get_queryset().filter(department=department))
        else:
            # 只有董事会才能通过department搜索，其他人不行，所以只用写董事会
            if department_id:
                queryset = self.filter_queryset(self.get_queryset().filter(department_id=department_id))
            else:
                queryset = self.filter_queryset(self.get_queryset())

        if realname:
            queryset = self.filter_queryset(self.get_queryset().filter(realname__icontains=realname))
        if date_joined:
            try:
                start_date = datetime.strptime(date_joined[0], '%Y-%m-%d')
                end_date = datetime.strptime(date_joined[1], '%Y-%m-%d')
                queryset = self.filter_queryset(self.get_queryset().filter(date_joined__range=(start_date, end_date)))
            except Exception:
                pass

        # 动态调整分页大小
        if size:
            # print(size)
            try:
                size = int(size)
                self.paginator.page_size = size  # 设置分页大小
            except ValueError:
                # 如果`size`参数不是有效的整数，返回错误响应
                raise exceptions.ValidationError("分页参数`size`无效，应为正整数。")

        # 处理分页逻辑
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)

        return Response(serializer.data)

    def update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return super().update(request, *args, **kwargs)

    # 创建新员工的方法
    def create(self, request, *args, **kwargs):
        # 序列化请求数据并设置请求上下文
        serializer = self.get_serializer(data=request.data)

        try:
            serializer.is_valid(raise_exception=True)  # 校验序列化数据
        except Exception :
            print(list(serializer.errors.values())[0][0])
            return Response(data={'detail':list(serializer.errors.values())[0][0]}, status=status.HTTP_400_BAD_REQUEST)  # 返回详细错误信息

        realname = serializer.validated_data['realname']
        email = serializer.validated_data['email']
        password = serializer.validated_data['password']

        # 创建用户并设置密码、部门等属性
        user = OAUser.objects.create(realname=realname, email=email)
        user.set_password(password)  # 密码加密
        user.department = request.user.department
        user.save()

        # 发送激活邮件 I/O:网络请求，文件读写，异步防止堵塞
        send_active_email(request, email)

        # 返回创建成功的响应
        return Response(serializer.data, status=status.HTTP_201_CREATED)



# 下载员工信息
class StaffDownloadView(viewsets.ModelViewSet):
    queryset = OAUser.objects.all()

    def list(self, request, *args, **kwargs):

        current_user = self.request.user

        pks = request.query_params.get('pks')
        try:
            pks = json.loads(pks)
        except Exception:
            return Response({"detail": "员工参数错误"}, status=status.HTTP_400_BAD_REQUEST)
        try:
            if current_user.department.name != '董事会':
                if current_user.uid != current_user.department.leader.uid:
                    return JsonResponse({"detail": "没有权限下载"}, status=status.HTTP_403_FORBIDDEN)
                else:
                    queryset = self.filter_queryset(self.get_queryset().filter(department=current_user.department))
            else:
                queryset = self.filter_queryset(self.get_queryset().filter(pk__in=pks))

            result = queryset.values("realname", "email", "department__name", "date_joined", "status")
            staff_df = pd.DataFrame(list(result))
            staff_df = staff_df.rename(
                columns={"realname": "真实姓名", "email": "邮箱", "department__name": "部门", "date_joined": "入职时间",
                         "status": "状态"})
            response = HttpResponse(content_type='application/xlsx')
            response['Content-Disposition'] = 'attachment; filename="员工信息.xlsx"'
            with pd.ExcelWriter(response) as writer:
                staff_df.to_excel(writer, sheet_name='员工信息')
            return response
        except Exception as e:
            print(e)
            return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)


# 批量上传新员工信息
class StaffUploadView(viewsets.ModelViewSet):
    queryset = OAUser.objects.all()
    serializer_class = StaffUploadSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)  # 校验序列化数据
        file = serializer.validated_data.get('file')
        current_user = self.request.user

        if current_user.department.name != '董事会' or current_user.uid != current_user.department.leader.uid:
            return Response({'detail': '您无权上传员工信息'}, status=status.HTTP_403_FORBIDDEN)

        staff_df = pd.read_excel(file)
        users = []
        for index, row in staff_df.iterrows():
            # 获取部门
            try:
                if current_user.department.name != '董事会':
                    department = current_user.department
                else:
                    department = OADepartment.objects.filter(name=row['部门']).first()

                if not department:
                    return Response({"detail": f"{row['部门']}不存在"}, status=status.HTTP_400_BAD_REQUEST)

                try:
                    email = row['邮箱']
                    realname = row['姓名']
                    password = "111111"
                    user = OAUser(realname=realname, email=email, department=department,
                                  status=UserStatusChoices.UNACTIVATED)
                    user.set_password(password)
                    users.append(user)
                except Exception:
                    return Response({"detail": "邮箱或姓名列有误"}, status=status.HTTP_400_BAD_REQUEST)

            except Exception as e:
                return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)

        try:
            #原子操作(有一条失败，整个操作都失败)
            with transaction.atomic():
                OAUser.objects.bulk_create(users)
        except Exception as e:
            return Response({"detail": "员工数据添加错误"}, status=status.HTTP_400_BAD_REQUEST)

        #异步给每个新员工发送邮件
        for user in users:
            send_active_email(request, user.email)

        return Response()

# 测试celery异步
class TestCeleryView(APIView):
    def get(self, request):
        debug_task.delay()
        return Response({'detail': 'success'})
